#ifndef SOURCETRACERAY_TRACERAY_HPP
#define SOURCETRACERAY_TRACERAY_HPP
#include "../sdk/EngineTrace.hpp"

namespace TraceRay {

    bool toggle = false;
    IEngineTrace* pEngineTrace = nullptr;
    DWORD localPlayer = 0;
    DWORD curEntity = 0;
    int count = 0;
    Vector localPlayerPos = Vector();
    Vector curEntityPos = Vector();

    void* GetInterface(const char* szModule, const char* szInterface) {

        auto CreateInterface = reinterpret_cast<void* (*)(const char*, int*)>(GetProcAddress(GetModuleHandleA(szModule), "CreateInterface"));
        if (CreateInterface != nullptr)
            return CreateInterface(szInterface, nullptr);

        return nullptr;
    }

    bool CheckVisible(IEngineTrace* tracer, Entity pLocalPlayer, Entity pEntity, const Vector& pointA, const Vector& pointB) {

        Ray_t ray;
        CGameTrace  trace;
        CTraceFilter filter;
        ray.Init(pointA, pointB);
        filter.pSkip1 = reinterpret_cast<Entity>(pLocalPlayer);

        tracer->TraceRay(ray, 0x46004009, &filter, &trace);

        return trace.m_pEnt == (void*)pEntity || trace.fraction > 0.97f;
    }

    void Init() {

        pEngineTrace = reinterpret_cast<IEngineTrace*>(GetInterface("engine.dll", "EngineTraceClient004"));
    }

    bool OnRender2D(DWORD hEngineDll, DWORD hClientDll) {

        if (!toggle) return false;
        static bool inited = false;
        if (!inited) {

            Init();
            inited = true;
        }

        auto* localPlayerPtr = reinterpret_cast<DWORD*>(hClientDll + m_dwLocalPlayer);
        if (reinterpret_cast<DWORD>(localPlayerPtr) == 0) return false;
        localPlayer = *(reinterpret_cast<DWORD*>(hClientDll + m_dwLocalPlayer));
        if (localPlayer == 0) return false;
        localPlayerPos.x = *(reinterpret_cast<float*>(localPlayer + m_dwLocation));
        localPlayerPos.y = *(reinterpret_cast<float*>(localPlayer + m_dwLocation + 4));
        localPlayerPos.z = *(reinterpret_cast<float*>(localPlayer + m_dwLocation + 8)) + 64.06256f;

        count = *(reinterpret_cast<int*>(hClientDll + m_dwCount));
        ImGui::Begin("Players");
        for(int i = 0; i < (count - 1); i++) {

            curEntity = *(reinterpret_cast<DWORD*>(hClientDll + m_dwEntityList + i * 0x10));
            curEntityPos.x = *(reinterpret_cast<float*>(curEntity + m_dwLocation));
            curEntityPos.y = *(reinterpret_cast<float*>(curEntity + m_dwLocation + 4));
            curEntityPos.z = *(reinterpret_cast<float*>(curEntity + m_dwLocation + 8)) + 64.06256f;
            if (ImGui::CollapsingHeader("Player")) {

                ImGui::Text("Addr: %lx", curEntity);
                ImGui::Text("Location: %f\t%f\t%f", curEntityPos.x, curEntityPos.y, curEntityPos.z);
            }

            DWORD pGlowObjectManager = *(reinterpret_cast<DWORD*>(hClientDll + m_dwGlowObjectManager));
            DWORD pGlowIndex = *(reinterpret_cast<DWORD*>(curEntity + m_dwGlowIndex));
            DWORD pGlow = pGlowIndex * 7;

            *(reinterpret_cast<unsigned char*>(pGlowObjectManager + pGlow * 8 + 0x28)) = static_cast<unsigned char>(1);

            // 这里只检测大概在敌人腹部的一个位置点，配合骨骼点可以做出来露哪打哪
            if (CheckVisible(pEngineTrace, reinterpret_cast<Entity>(localPlayer), reinterpret_cast<Entity>(curEntity), localPlayerPos, curEntityPos)) {

                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8)) = 1.0f;
                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8 + 4)) = 0.0f;
                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8 + 4 + 4)) = 0.0f;
            } else {

                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8)) = 0.0f;
                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8 + 4)) = 1.0f;
                *(reinterpret_cast<float*>(pGlowObjectManager + pGlow * 8 + 0x8 + 4 + 4)) = 0.0f;
            }
            *(float*)(pGlowObjectManager + pGlow * 8 + 0x8 + 4 + 4 + 4) = 1.0f;
        }
        ImGui::End();

        return true;
    }
}

#endif //SOURCETRACERAY_TRACERAY_HPP
